| 1 | --- |
| 2 | import type { Page, GetStaticPathsOptions } from "astro"; |
| 3 | import type { CollectionEntry } from "astro:content"; |
| 4 | import { getCollection } from "astro:content"; |
| 5 | import PageLayout from "@/layouts/Base"; |
| 6 | import PostPreview from "@/components/blog/PostPreview"; |
| 7 | import Pagination from "@/components/Paginator"; |
| 8 | import { getUniqueTags, sortMDByDate } from "@/utils"; |
| 9 | |
| 10 | export async function getStaticPaths({ paginate }: GetStaticPathsOptions) { |
| 11 | const allPosts = await getCollection("post"); |
| 12 | const allPostsByDate = sortMDByDate(allPosts); |
| 13 | const uniqueTags = getUniqueTags(allPosts); |
| 14 | return paginate(allPostsByDate, { props: { uniqueTags }, pageSize: 10 }); |
| 15 | } |
| 16 | |
| 17 | interface Props { |
| 18 | page: Page<CollectionEntry<"post">>; |
| 19 | uniqueTags: string[]; |
| 20 | } |
| 21 | |
| 22 | const { page, uniqueTags } = Astro.props; |
| 23 | |
| 24 | const meta = { |
| 25 | title: "Posts", |
| 26 | description: "A collection of posts by me for an Asto starter theme", |
| 27 | }; |
| 28 | |
| 29 | const paginationProps = { |
| 30 | ...(page.url.prev && { |
| 31 | prevUrl: { |
| 32 | url: page.url.prev, |
| 33 | text: `← Previous Posts`, |
| 34 | }, |
| 35 | }), |
| 36 | ...(page.url.next && { |
| 37 | nextUrl: { |
| 38 | url: page.url.next, |
| 39 | text: `Next Posts →`, |
| 40 | }, |
| 41 | }), |
| 42 | }; |
| 43 | --- |
| 44 | |
| 45 | <PageLayout meta={meta}> |
| 46 | <h1 class="title mb-6">Posts</h1> |
| 47 | <div class="grid gap-y-16 sm:grid-cols-[3fr_1fr] sm:gap-x-8"> |
| 48 | <section aria-label="Blog post list"> |
| 49 | <ul class="space-y-8 text-left"> |
| 50 | { |
| 51 | page.data.map((p) => ( |
| 52 | <li class="flex flex-col flex-wrap gap-x-2 sm:flex-row [&_q]:w-full"> |
| 53 | <PostPreview post={p} as="h2" withDesc /> |
| 54 | </li> |
| 55 | )) |
| 56 | } |
| 57 | </ul> |
| 58 | <Pagination {...paginationProps} /> |
| 59 | </section> |
| 60 | { |
| 61 | uniqueTags.length && ( |
| 62 | <aside> |
| 63 | <h2 class="mb-4 flex items-center text-lg font-semibold"> |
| 64 | <svg |
| 65 | aria-hidden="true" |
| 66 | xmlns="http://www.w3.org/2000/svg" |
| 67 | class="h-6 w-6" |
| 68 | viewBox="0 0 24 24" |
| 69 | stroke-width="1.5" |
| 70 | stroke="currentColor" |
| 71 | fill="none" |
| 72 | stroke-linecap="round" |
| 73 | stroke-linejoin="round" |
| 74 | > |
| 75 | <path stroke="none" d="M0 0h24v24H0z" fill="none" /> |
| 76 | <path d="M7.859 6h-2.834a2.025 2.025 0 0 0 -2.025 2.025v2.834c0 .537 .213 1.052 .593 1.432l6.116 6.116a2.025 2.025 0 0 0 2.864 0l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-6.117 -6.116a2.025 2.025 0 0 0 -1.431 -.593z" /> |
| 77 | <path d="M17.573 18.407l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-7.117 -7.116" /> |
| 78 | <path d="M6 9h-.01" /> |
| 79 | </svg> |
| 80 | Tags |
| 81 | </h2> |
| 82 | <ul class="flex flex-wrap gap-2 text-bgColor"> |
| 83 | {uniqueTags.map((tag) => ( |
| 84 | <li> |
| 85 | <a |
| 86 | class="flex items-center justify-center rounded-lg bg-accent p-1" |
| 87 | href={`/tags/${tag}`} |
| 88 | aria-label={`View all posts with the tag: ${tag}`} |
| 89 | > |
| 90 | {tag} |
| 91 | </a> |
| 92 | </li> |
| 93 | ))} |
| 94 | </ul> |
| 95 | <span class="mt-4 block sm:text-right"> |
| 96 | <a class="sm:hover:text-accent" href="/tags" aria-label="View all blog categories"> |
| 97 | View all → |
| 98 | </a> |
| 99 | </span> |
| 100 | </aside> |
| 101 | ) |
| 102 | } |
| 103 | </div> |
| 104 | </PageLayout> |